Date-time range
canonStart and end with time, all-day toggle and duration presets.
M4c (owner 28 Sep 2026, approved): all-day renders the canonical DateRangeField (from–to in one field, shared calendar, day count) instead of two DateFields with their own day arithmetic — one shape for a range of days; `.dp-field.range` ends share the field width (width 0 + flex 1), so the term row no longer overflows on 390 px (acrm branch feat/celodenni-rozsah). acrm !4087 (28 Sep 2026, owner): the visible duration next to times uses `fmtDurShort` — „45 m“ · „1 h“ · „1 h 30 m“ (in the context of time „m“ = minutes). Screen readers keep the full „min“ via `fmtDur` (TimeField option aria-label, DateTimeRange hidden live text) so „m“ is not read as metres. Other durations in the app (timeline, Setkání, tasks, reminders) keep „min“.
Used in 3 files · 3 areas · 3× — components/calendar, components/meetings, pages/ZasedackyPage
@acrm/ui <DateTimeRangeField>.dp-stack .dp-termin .dp-timegroup .dp-switches +3SourceStoryLegacy card dates.htmlThe canonical event term ("Termín" of a meeting or calendar entry). React <DateTimeRangeField> (packages/ui/src/components/DateTimeRangeField.tsx) composes Date field + two Time fields in .dp-stack / .dp-termin / .dp-timegroup, the switches row .dp-switches ("Celý den" and the caller's extras such as "Opakovat") and the availability line .dp-status. Row order follows Google Calendar (AD, ACRM-136, 7 Sep 2026): first the date and the time, then the switches.
When to use
- Meeting dialog, calendar event, room booking — anything with a start and an end on a clock.
- All-day events: the toggle hides the times and the day row becomes the canonical Date range field (
<DateRangeField>: from–to in one field, one shared calendar, day count) — owner 28 Sep 2026 (acrm M4c): one shape for a range of days in the DS, not two Date fields with their own day arithmetic. A one-day all-day event has from = to. - Overnight events (
allowOvernight): an end earlier than the start is not an error but "přes půlnoc"; the end day is computed (+1).
When not to use
- A due date with an optional time (task) — Date field + Time field in the task panel (
.dp-addtime/.dp-timerow). - A reporting period — Date range.
- Two dates only, no clock — Date range.
Anatomy
.dp-stack: column, gap--sp-3, left-aligned — one gap for every row under the fields, no ad-hoc margins.- Row 1
.dp-termin: timed —<DateField futureBias ariaLabel="Datum">+.dp-timegroup(Time field "Od",.dp-sep, Time field "Do" withgetStart,.dp-durlength); all-day —<DateRangeField futureBias presets={[]} fromLabel="Datum" toLabel="Datum konce">(past-range presets do not fit a future event) +.dp-durday count when longer than one day. The range field swaps the ends itself. Nothing else sits in this row; the range field may shrink (.dp-termin > .dp-fieldset { min-width: 0 }, full row on phone). - Row 2
.dp-switches: the canonical Switch "Celý den" (whenallowAllDay, default true) followed bydayExtrasfrom the caller — the meeting dialog puts "Opakovat" and, once on, its frequency · until · end row here. The row is not rendered when there is nothing to put in it. .dp-dur:--small,--fg-secondary;.overnote in--warning-ink("přes půlnoc", "končí 27. 8.")..dp-status.ok(--positive-ink) /.busy(--critical-ink, × icon): text from theavailabilitycallback, or the built-in overnight error whenallowOvernightis false.- Value contract
{ date, from, to, allDay, toDate }— minutes from midnight, ISO days; the component keepstoDatecomputed so callers composestartsAt/endsAtonly.
Best practices
- Let the start drag the end: moving "od" keeps the duration (code does this); moving the date moves the whole block.
- Provide
availabilityfor meetings and rooms so the status line answers "is it free" in place. - Use
allowOvernightfor meetings, keep it off for rooms where an end before start is a typo.
- A second date picker asking for the end day of every timed meeting —
allowMultiDaywas removed for that reason. - Duration presets (15 min … 2 h) — removed 6 Sep 2026; the length is written as text after "Do" (
.dp-dur). - Anything but the date and the time in row 1 — switches and recurrence live in
.dp-switches. - Status text as a paragraph — one line, state first.
- A custom toggle for all-day — the canonical control is
<Switch>from@acrm/uiin.dp-switches. The old.dp-alldaycheckbox was removed on 6 Sep 2026 (AD: „předělat na switch“) and the class no longer exists indate-picker.css.
Content
- Length via
fmtDur("45 min", "1 h 30 min"); days viafmtDays("2 dny"). - Overnight note "přes půlnoc"; longer terms "končí 27. 8." (date by
formatDate). - Built-in error: "Konec je před začátkem — schůzka přes půlnoc není povolená."
- Toggle label "Celý den"; field labels "Datum", "Datum konce", "Od", "Do" (sentence case).
- Live region reads "9:00 až 10:30, 1 h 30 min" after every change.
Related
- date-field, time-field — the parts.
- date-range — dates only.
- calendar, picker-panel — the layers the parts open.